#!/bin/bash

#    / **  
#    * 文件名：安装linux软件
#    * 版权： Copyright 谢振斌  All Rights Reserved.  
#    * 修改内容：新增  
#    * 修改人： 谢振斌  
#    * 修改时间：2021-9-21 
#    */  



# Init option 
Color_off='\033[0m'       # Text Reset

# terminal color template 
# Regular Colors
Black='\033[0;30m'        # Black
Red='\033[0;31m'          # Red
Green='\033[0;32m'        # Green
Yellow='\033[0;33m'       # Yellow
Blue='\033[0;34m'         # Blue
Purple='\033[0;35m'       # Purple
Cyan='\033[0;36m'         # Cyan
White='\033[0;37m'        # White



# version
Version='1.3.0'
#System name
System="$(uname -s)"



# need_cmd {{{
need_cmd () {
  if ! hash "$1" &>/dev/null; then
    error "需要 '$1' （找不到命令）"
    exit 1
  fi
}
# }}}

# success/info/error/warn
msg() {
  printf '%b\n' "$1" >&2
}

success() {
  msg "${Green}[✔]${Color_off} ${1}${2}"
}

info() {
  msg "${Blue}[➭]${Color_off} ${1}${2}"
}

error() {
  msg "${Red}[✘]${Color_off} ${1}${2}"
  exit 1
}

warn () {
  msg "${Yellow}[⚠]${Color_off} ${1}${2}"
}




#    / **  
#    *〈一句话功能简述〉  
#    *〈功能详细描述〉  
#    * @param [参数1] [参数1说明]  
#    * @param [参数2] [参数2说明]  
#    * @return [返回类型说明]  
#    * @exception/throws [违例类型] [违例说明]  
#    * @see [类、类#方法、类#成员]  
#    * @deprecated  
#    */  
function fun1()
{  
  echo "helld world !"

  # 在shell中：
  # $0: 获取当前脚本的名称
  # $#: 传递给脚本的参数个数
  # $$: shell脚本的进程号
  # $1, $2, $3...：脚本程序的参数

    # $?: 获取上一命令或函数打印输出结果

    # 拆分字符串 
    # 原理：
    # ${parameter//pattern/string} 
    # 用string来替换parameter变量中所有匹配的pattern
    # 例子：以 , 拆分字符串
    #  string="hello,shell,split,test" 
    #  array=(${string//,/ }) 
    #  echo "[Debug] 循环输出 array[]所有值="${array[1]}
    # for var in ${array[@]}
    # do
    #    echo $var
    # done
    #  参考 [Shell_Linux Shell 中实现字符串切割的几种方法](https://blog.csdn.net/u010003835/article/details/80750003)

    # shell中各种括号的作用()、(())、[]、[[]]、{}
    # 参考资料 [hell中各种括号的作用](https://blog.csdn.net/taiyang1987912/article/details/39551385)

    # 判断一个变量是否为空方法
    # 例：
    # if [ ! -n "$1" ] ;then
    #    echo "you have not input a word!"
    # else
    #    echo "the word you input is $1"
    # fi
    # 例2：
    # para1=
    # if [ ! $para1 ]; then
    #  echo "IS NULL"
    # else
    #  echo "NOT NULL"
    # fi
    # 例3：
    # dmin=
    # if test -z "$dmin"
    # then
    #   echo "dmin is not set!"
    # else 
    #   echo "dmin is set !"
    # fi
    # 例4：
    # dmin=
    # if [ "$dmin" = "" ]
    # then
    #   echo "dmin is not set!"
    # else 
    #   echo "dmin is set !"
    # fidmin=
    # if [ "$dmin" = "" ]
    # then
    #   echo "dmin is not set!"
    # else 
    #   echo "dmin is set !"
    # fi
    # 参考资料 - [Shell脚本中判断输入变量或者参数是否为空的方法](https://www.jb51.net/article/56550.htm)


}



#    / **  
#    *〈 判断shell系统类型 〉  
#    *〈功能详细描述〉  
#    * @param [参数1] [参数1说明]  
#    * @param [参数2] [参数2说明]  
#    * @return [返回类型说明]  String [linux、osx、bsd] 
#    * @exception/throws [违例类型] [违例说明]  
#    * @see [类、类#方法、类#成员]  
#    * @deprecated  
#    */  
function getShellOStype()
{
    SHELL_PLATFORM='unknown';
    ## echo "[Debug] SHELL_PLATFORM=${SHELL_PLATFORM}"

    ## echo $OSTYPE | tr '[A-Z]' '[a-z]'"
    shellostypestring=`echo $OSTYPE`;
    ## echo "[Debug] shellostypestring=${shellostypestring}"

    ## 从字符串中识别shell系统类型
    case "${shellostypestring}" in
        *'linux'*   ) SHELL_PLATFORM='linux'    ;;
        *'darwin'*  ) SHELL_PLATFORM='osx'      ;;
        *'bsd'*     ) SHELL_PLATFORM='bsd'      ;;
    esac

    # if [[ $SHELL_PLATFORM == 'linux' || $SHELL_PLATFORM == 'bsd' ]]; then
    #    echo "[Debug] linux"
    # elif [[ $SHELL_PLATFORM == 'osx' ]]; then
    #    # $SHELL_PLATFORM == 'bsd'
    #    echo "[Debug] osx Shell"
    # elif [[ $SHELL_PLATFORM == 'bsd' || $SHELL_PLATFORM == 'osx'  ]]; then
    #    echo "[Debug] bad shell"
    # else
    #    echo "[Debug] unknown"
    # fi

    # 返回值
    echo $SHELL_PLATFORM;
}


#    / **  
#    *〈获得linux发行版本名称〉  
#    *〈功能详细描述〉  
#    * @param [参数1] [参数1说明]  
#    * @param [参数2] [参数2说明]  
#    * @return [返回类型说明]  
#    * @exception/throws [违例类型] [违例说明]  
#    * @see [类、类#方法、类#成员]  
#    * @deprecated  
#    */  
function getDistName()
{
  if grep -Eqii "Arch Linux" /etc/issue || grep -Eq "Arch Linux" /etc/*-release; then
        DISTRO='Arch Linux'
        PM='pacman'
    elif grep -Eqii "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
        DISTRO='CentOS'
        PM='yum'
    elif grep -Eqi "Red Hat Enterprise Linux Server" /etc/issue || grep -Eq "Red Hat Enterprise Linux Server" /etc/*-release; then
        DISTRO='RHEL'
        PM='yum'
    elif grep -Eqi "Aliyun" /etc/issue || grep -Eq "Aliyun" /etc/*-release; then
        DISTRO='Aliyun'
        PM='yum'
    elif grep -Eqi "Fedora" /etc/issue || grep -Eq "Fedora" /etc/*-release; then
        DISTRO='Fedora'
        PM='yum'
    elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then
        DISTRO='Debian'
        PM='apt'
    elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then
        DISTRO='Ubuntu'
        PM='apt'
    elif grep -Eqi "Raspbian" /etc/issue || grep -Eq "Raspbian" /etc/*-release; then
        DISTRO='Raspbian'
        PM='apt'
    else
        DISTRO='unknow'
    fi

    # 返回值
    echo $DISTRO;
}

#    / **  
#    *〈 判断文件夹是否存在，不存在则，建立链接，存在则备份并建立链接 〉  
#    *〈功能详细描述〉  
#    * @param [参数1] [文件路径]  
#    * @param [参数2] [链接建立命令]  
#    * @return [返回类型说明]  
#    * @exception/throws [违例类型] [违例说明]  
#    * @see [类、类#方法、类#成员]  
#    * @deprecated  
#    * 例子：
#    *      判断文件夹 ~/.vim是否存在，不存在则执行命令，存在则备份后执行命令 
#    *      folderPath=${HOME}"/.vim"
#    *      echo "[Debug] folderPath= ${folderPath}"
#    *      commandStr="mkdir -p ${folderPath}"
#    *      echo "[Debug] commandStr=${commandStr}"
#    *      bakAndLinkFolder ${folderPath} "${commandStr}"
#    *      # 注：参数中带有空格，如果直接写的话，会从空格处自动切分开。解决方法：将这个引用变量用双引号括起来
#    */  
function bakAndLinkFolder()
{

    echo "[Debug]: bakAndLinkFolder !";
    # folderPath=${HOME}"/.vim"
    folderPath=$1;
    echo "[INFO]: bakAndLinkFolder=${folderPath}";
    commandStr=$2;
    echo "[INFO]: commandStr=${commandStr}";
    # 判断是文件夹是否已经存在
    if [ ! -d "$folderPath" ]; then
        echo "[INFO]: ${folderPath} 不存在!";
    else
        echo "[INFO]: ${folderPath} 已经存在!";
        # 备份文件
        echo "[INFO] 备份文件夹 ${folderPath}";
        cmdStr="mv ${folderPath} ${folderPath}-`date +%y%m%d%H%M%S`";
        echo "执行命令: ${cmdStr}";
        ${cmdStr}
    fi
    # 命令拼接
    #echo "[INFO]: 创建文件夹软链接";
    #commandStr="ln -s  "${dir}"/vimrc  "${HOME}"/.vimrc"
    echo "执行命令: ${commandStr}";
    ${commandStr}
}

#    / **  
#    *〈 判断文件是否存在，不存在则执行命令，存在则备份后执行命令 〉  
#    *〈功能详细描述〉  
#    * @param [参数1] [文件路径]  
#    * @param [参数2] [要执行的命令]  
#    * @return [返回类型说明]  
#    * @exception/throws [违例类型] [违例说明]  
#    * @see [类、类#方法、类#成员]  
#    * @deprecated  
#    * 例子：
#    *  # 判断文件~/.vimrc 是否存在，不存在则执行命令，存在则备份后执行命令 
#    *  configFilePath=${HOME}"/.vimrc"
#    *  commandStr="ln -s  ${dir}/vimrc  ${configFilePath}"
#    *  bakAndLinkFile ${configFilePath} "${commandStr}"
#    *  # 注：参数中带有空格，如果直接写的话，会从空格处自动切分开。解决方法：将这个引用变量用双引号括起来
#    */  
function bakAndLinkFile()
{

    # configFilePath=${HOME}"/.vimrc"
    configFilePath=$1;
    commandStr=$2;
    # 判断是文件是否已经存在
    if [ ! -f "$configFilePath" ]; then
        echo "[INFO]: ${configFilePath} 不存在!";
    else
        echo "[INFO]: ${configFilePath} 已经存在!";
        # 备份文件
        echo "[INFO] 备份文件 ${configFilePath}";
        cmdStr="mv ${configFilePath} ${configFilePath}-`date +%y%m%d%H%M%S`";
        echo "执行命令: ${cmdStr}";
        ${cmdStr}
    fi
    # 命令拼接
    #echo "[INFO]: 创建文件软链接";
    #commandStr="ln -s  "${dir}"/vimrc  "${HOME}"/.vimrc"
    echo "执行命令: ${commandStr}";
    ${commandStr}
}

#    / **  
#    *〈 安装软件 〉  
#    *〈功能详细描述〉  
#    * @param [参数1] [软件名称]  
#    * @param [参数2] [用来判断是否已经安装的软件名称，可为空，为空则，与参数1来判断是否存在]  
#    * @return [返回类型说明]  
#    * @exception/throws [违例类型] [违例说明]  
#    * @see [类、类#方法、类#成员]  
#    * @deprecated  
#    */  
function installSoftware()
{
    echo "[INFO] 安装软件";
    softwareName=$1;
    echo "[Debug] softwareName="${softwareName};
    # 判断是否已经安装
    #cmdStr="which ${softwareName}"
    #echo "[Debug] cmdStr="${cmdStr}
    #if [ ! -x "$( which ${softwareName} )" ]; then
    #    echo "[Debug] 未安装软="${softwareName}
    #else
    #    echo "[Debug] 已经安装软="${softwareName}
    #fi
    #exit
    softwareName2=$2;
    if [  ! $softwareName2 ];then
        echo "[INFO] 软件安装与用来判断是否安装的名称相同"
        softwareName2=${softwareName};
        echo "[Debug] softwareName2="${softwareName2};
    else
        echo "[INFO] 软件安装名称与用来判断是否安装的名称不同！";
        #softwareName2=$2;
        echo "[Debug] softwareName2="${softwareName2};
    fi
    echo "[INFO] 判断系统中是否已经存在"${softwareName2};
    if [ ! -x "$( which ${softwareName2} )" ]; then
        echo "[INFO] 软件${softwareName}未安装！"
        # 获取当前shell系统（判断是mac、还是linux）
        shellSystemType=$(getShellOStype)
        echo "[Debug] shellSystemType="${shellSystemType}
        if [ "$shellSystemType" == "linux" ]; then
            # 获取当前系统发行版本
            linuxSystemDistType=$(getDistName)
            echo "[Debug] linuxSystemDistType="${linuxSystemDistType}
            # 命令拼接
            #cmdStr="ln -s  "${dir}"/zshrc-oh-my-sh  "${HOME}"/.zshrc"
            #cmdStr="git clone "${URL}${pluginsName}" "${pluginsPath}
            #echo "执行命令: ${cmdStr}"
            #${cmdStr}
            if [ "$linuxSystemDistType" == "CentOS" ]; then
                echo "[Debug] ======= CentOS"
                # 执行另一个脚本
                # /bin/bash ./zsh1.sh  
                #cmdStr="ln -s  "${dir}"/zshrc-oh-my-sh  "${HOME}"/.zshrc"
                cmdStr="yum install "${softwareName}
                echo "执行命令: ${cmdStr}"
                ${cmdStr}
            elif [ "$linuxSystemDistType" == "Arch Linux" ] ; then
                echo "[Debug] ======= Arch Linux"
                cmdStr="yay -S "${softwareName}
                echo "执行命令: ${cmdStr}"
                ${cmdStr}
            else
                echo "[Debug] ======= unknow linux dist"
                echo "[INFO] 不知道当前linux系统是什么发行版本，不知到该用什么包管理软件进行安装！软件${systemType}！"
            fi
      elif [ "$shellSystemType" == "osx" ]; then
           echo "[Debug] ======= shellSystemType是darwin，所以是 osx（macOS）"
           # 权限设置，解决部分软件无法安装问题：如 lua
           cmdStr="sudo chown -R $(whoami) /usr/local/include /usr/local/lib /usr/local/lib/pkgconfig"
           echo "执行命令: ${cmdStr}"
           ${cmdStr}
           cmdStr="chmod u+w /usr/local/include /usr/local/lib /usr/local/lib/pkgconfig"
           echo "执行命令: ${cmdStr}"
           ${cmdStr}
           # 使用软件包管理器安装软件
           cmdStr="brew install "${softwareName}
           echo "执行命令: ${cmdStr}"
           ${cmdStr}
      else
        echo "[Debug] ======= unknow shell system type"
        echo "[INFO] 不知道当前系统是 linux bsd osx（macOS）！不知道该用什么包管理器安装软件${systemType}！"
      fi 
      if [ ! $? -eq 0 ]; then
        echo ""
        echo "[ERROR]: 安装软件${softwareName}  失败 !!！ 退出"
        exit
      fi
    else
        echo "[INFO] 软件${softwareName}已经存在！"
    fi
}


function download_font () {
  url="https://ghproxy.com/https://raw.githubusercontent.com/wsdjeg/DotFiles/master/local/share/fonts/$1"
  path="$HOME/.local/share/fonts/$1"
  if [[ -f "$path" ]]
  then
    success "已下载 $1"
  else
    info "正在下载 $1"
    curl -s -o "$path" "$url"
    success "已下载 $1"
  fi
}




function install_fonts () {
  if [[ ! -d "$HOME/.local/share/fonts" ]]; then
    mkdir -p $HOME/.local/share/fonts
  fi
  download_font "DejaVu Sans Mono Bold Oblique for Powerline.ttf"
  download_font "DejaVu Sans Mono Bold for Powerline.ttf"
  download_font "DejaVu Sans Mono Oblique for Powerline.ttf"
  download_font "DejaVu Sans Mono for Powerline.ttf"
  download_font "DroidSansMonoForPowerlinePlusNerdFileTypesMono.otf"
  download_font "Ubuntu Mono derivative Powerline Nerd Font Complete.ttf"
  download_font "WEBDINGS.TTF"
  download_font "WINGDNG2.ttf"
  download_font "WINGDNG3.ttf"
  download_font "devicons.ttf"
  download_font "mtextra.ttf"
  download_font "symbol.ttf"
  download_font "wingding.ttf"
  info "正在构建字体缓存，请稍等..."
  if [ $System == "Darwin" ];then
    if [ ! -e "$HOME/Library/Fonts" ];then
      mkdir "$HOME/Library/Fonts"
    fi 
    cp $HOME/.local/share/fonts/* $HOME/Library/Fonts/
  else
    fc-cache -fv > /dev/null
    mkfontdir "$HOME/.local/share/fonts" > /dev/null
    mkfontscale "$HOME/.local/share/fonts" > /dev/null
  fi
  success "字体安装已完成!"
}


function spacevim_fetch_repo () {
  if [[ -d "$HOME/.SpaceVim" ]]; then
    info "正在更新 SpaceVim..."
    cd "$HOME/.SpaceVim"
    git pull
    cd - > /dev/null 2>&1
    success "SpaceVim 更新已完成"
  else
    info "正在安装 SpaceVim..."
    git clone https://ghproxy.com/https://github.com/SpaceVim/SpaceVim.git "$HOME/.SpaceVim"
    success "SpaceVim 安装已完成"
  fi
}


function install_package_manager () {
  if [[ ! -d "$HOME/.cache/vimfiles/repos/github.com/Shougo/dein.vim" ]]; then
    info "正在安装 dein.vim"
    git clone https://ghproxy.com/https://github.com/Shougo/dein.vim.git $HOME/.cache/vimfiles/repos/github.com/Shougo/dein.vim
    success "dein.vim 安装已完成"
  fi
}

#    / **  
#    *〈流程控制〉  
#    *〈该脚本的主函数〉  
#    * @param [无]  
#    * @return [无]  
#    * @exception/throws [无]  
#    * @deprecated  
#    */  
function processControlMain()  
{  
    # 打印当前系统时间  
    echo "Start..."  
    date  

    # 此处是你的代码  
    # ...  
    # fun1

    echo "[INFO] 安装 vim"
    installSoftware vim

    spacevim_fetch_repo
    install_package_manager
    install_fonts

    # 执行另一个脚本
    # /bin/bash ./zsh2.sh
    # 打印当前系统时间  
    date  
    echo "The End."  
}  

# 执行入口 
# 进入脚本目录位置
cd `dirname $0`
# 获取当前脚本目录位置
shellfilepath=`pwd`'/'$0
# 打印脚本目录地址
echo "[INFO]: 脚本地址 "${shellfilepath}

if true  
# if false  
then  
    echo "[Debug] true"
    # 开始执行  从标准输入中读取并同时写入到标准输出和指定的文件上 
    ## 拼接日志文件地址
    #logfilepath=`pwd`'/'$0'.log'
    logfilepath=`pwd`'/'$0'-'$(date +%Y%m%d)'.log'
    #logfilepath=`pwd`'/'$0'-'$(date +%y%m%d-%H-%M-%S)'.log'
    ## 打印日志文件地址
    echo "[INFO]: 日志地址" ${logfilepath}
    processControlMain  | tee -a ${logfilepath}
else  
    echo "[Debug] false"  
    ## 函数单元测试  
    #  
fi  

# 脚本结束  

